export const trim = (str = '') => str.replace(/(^\s*)|(\s*$)/g, '')

/**
 * OSS图片裁切服务
 */
export const ossResize = (url, width = 100, height = 100) => {
  return `${url}?x-oss-process=image/resize,m_fill,h_${height},w_${width}`
}

export const dateParse = date => {
  if (date) {
    if (typeof date === 'string') {
      return new Date(date.replace(/\.0$/g, '').replace(/-/g, '/'))
    }
    if (typeof date === 'number') {
      return new Date(date)
    }
  }

  return date
}

export const getDaysInMonth = (year, month) => {
  return new Date(year, month, 0).getDate()
}

/**
 * 时间友好提示
 * 与当前时间相差60s以内(不包括60s)，显示1分钟内
 * 与当前时间相差60min以内(不包括60min)，显示XX分钟前
 * 与当前时间相差24h以内(不包括24h)，显示XX小时前
 * 与当前时间相差3d以内(不包括3d)，显示XX天前
 * 发布时间为今年，显示MM-dd
 * 发布时间不在今年， 显示yyyy-MM-dd
 * @param {String} date 需要显示的原始日期
 */
export const getFriendlyTime = date => {
  date = dateParse(date)
  if (!date) { return '' }

  let nowDate = new Date()
  let delta = (nowDate.getTime() - date.getTime()) / 1000

  if (delta < 60) {
    return '刚刚' // Math.floor(delta) + '秒前'
  } else if (delta < 3600) {
    return Math.floor(delta / 60) + '分钟前'
  } else if (delta < 8.64e4) {
    return Math.floor(delta / 3600) + '小时前'
  } else if (delta < 2.592e6) {
    return Math.floor(delta / 8.64e4) + '天前'
  } else if (delta < 3.1536e7) {
    return Math.floor(delta / 2.592e6) + '个月前'
  } else {
    return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
  }
}

/**
 * 防抖函数：
 * 把多个顺序地调用合并成一次，也就是在一定时间内，规定事件被触发的次数
 * @param {Function} func 需要被执行的函数
 * @param {Number} wait 等待时间
 * @param {Boolean} immediate 调用之前是否立即执行一次
 */
export const debounce = (func, wait, immediate) => {
  let timeout
  return function () {
    const context = this
    const args = arguments
    const later = () => {
      timeout = null
      if (!immediate) { func.apply(context, args) }
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) { func.apply(context, args) }
  }
}

/**
 * 节流函数：
 * 只允许一个函数在 X 毫秒内执行一次
 * 只有当上一次函数执行后过了你规定的时间间隔，才能进行下一次该函数的调用
 * 它保证在 X 毫秒内至少执行一次我们希望触发的事件
 * @param {Function} func 需要被执行的函数
 * @param {Number} wait 间隔时间
 * @param {Number} mustRun 至少执行一次的间隔时间
 */
export const throttle = (func, wait, mustRun = 20) => {
  let timeout
  let startTime = new Date().getTime()

  return function () {
    const context = this
    const args = arguments
    const curTime = new Date().getTime()

    clearTimeout(timeout)
    if (curTime - startTime >= mustRun) {
      // 如果达到了规定的触发时间间隔，触发 handler
      func.apply(context, args)
      startTime = curTime
    } else {
      // 没达到触发间隔，重新设定定时器
      timeout = setTimeout(func, wait)
    }
  }
}

/**
 * 把数组字符串 '["abc.jpg","def.jpg"]' 转换成数组
 * @param {String | Array} images 数组字符串
 */
export const getImagesFromString = (images) => {
  if (typeof images === 'string') {
    images = images.replace(/^\["(\S*)"\]$/, '$1').split('","')
  }
  return (images && images.length) ? images.filter(img => !!img) : []
}

export const isUndefined = value => value === undefined
export const isObject = value => {
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}
export const isFunction = value => {
  if (!isObject(value)) { return false }
  const tag = toString.call(value)
  return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object Proxy]'
}
export const isObjectLike = value => typeof value === 'object' && value !== null
export const isNumber = value => typeof value === 'number' || (isObjectLike(value) && toString.call(value) === '[object Number]')

// 简单处理精度丢失问题
export const calcNumber = (num = 0) => {
  return Math.round(num * 100) / 100
}

// 补位数
export const fillByChar = (num = '', len = 2, char = '0', before = true) => {
  const numLen = `${num}`.length
  if (numLen > len - 1) {
    return num
  }
  const fillStr = `${Array(len - numLen + 1).join(char)}`
  return before ? `${fillStr}${num}` : `${num}${fillStr}`
}
